<template>
	<el-select
		v-model="fieldValue"
		collapse-tags-tooltip
		collapse-tags
		clearable
		filterable
		@change="selectChange"
		v-bind="$attrs"
	>
		<slot v-bind="{ options }">
			<el-option
				v-for="item in options"
				:key="item.value"
				:label="item.label"
				:value="item.value"
				:disabled="item.disabled"
			/>
		</slot>
		<template v-for="(slotKey, slotIndex) in Object.keys($slots)" :key="slotIndex" v-slot:[slotKey]>
			<slot :name="slotKey"></slot>
		</template>
	</el-select>
</template>

<script setup name="MySelect">
// API_HOST
import { API_HOST } from '@/config';
// axios
import axios from '@u/axios';
import _camelCase from 'lodash/camelCase';
// 公共数据源
import { resultArrange, resultOutApi } from '@a/data';
import { GetProperty } from '@u';

/**模块store数据 */
import Com from '@s/com';
import Dict from '@s/dict';
const store = {
		com: Com(),
		dict: Dict()
	},
	emits = defineEmits(['update:modelValue', 'getLabel', 'getRow']);
/***
 * 参数属性
 * @property {Object[]} modelValue 默认值
 * @property {list[]} list 下拉列表数据
 * @property {Boolean} needAll 是否需要全部选项，默认为false
 * @property {Object} fillType 数据格式默认为{ label: 'dictLabel', value: 'dictValue' }
 * @property {String} type store.dispatch的方法名
 * @property {String，Function} api 数据请求地址，默认请求为·GET·方式，支持传递url地址、api请求方法两种
 * @property {Boolean} original 是否保留原始数据，默认为false
 */
const props = defineProps({
	modelValue: {
		default: ''
	},
	list: {
		type: Array,
		default: () => []
	},
	needAll: {
		type: Boolean,
		default: false
	},
	fileType: {
		type: [Object, String],
		default: () => ({ label: 'dictLabel', value: 'dictValue' })
	},
	type: {
		type: String,
		default: ''
	},
	api: {
		type: [String, Function],
		default: ''
	},
	original: {
		type: Boolean,
		default: false
	},
	selectData: {
		type: Object
	}
});

let options = ref([]),
	fieldValue = computed({
		get() {
			if (typeof props.modelValue === 'number') return `${props.modelValue}`;
			return props.modelValue;
		},
		set(val) {
			emits('update:modelValue', val);
		}
	}),
	dictType = computed(() =>
		props.type ? (props.type?.startsWith?.('GET') ? props.type : `GET${_camelCase(props.type)}`) : ''
	);

// 自定义的数据源逻辑
if (props.selectData) {
	// 静态数据源
	if (props.selectData.requestDataType == 0) {
		initialization(props.selectData.data || []);
	}
	// 动态数据、外部接口
	if (
		(props.selectData.requestDataType == 1 && props.selectData.reqID) ||
		(props.selectData.requestDataType == 3 && props.selectData.reqID)
	) {
		(props.selectData.requestDataType == 1 ? resultArrange : resultOutApi)({ id: props.selectData.reqID })
			.then((res) => {
				initialization(res.data || []);
			})
			.catch((err) => console.error(err));
	}
}

// 页面数据
watch(
	() => $store.chart.pageData,
	(val) => {
		if (props.selectData?.requestDataType == 2 && props.selectData?.pageKey && val) {
			initialization(GetProperty(val, props.selectData.pageKey) || []);
		}
	},
	{ deep: true }
);

watch(
	() => props.list,
	(val) => {
		if (val.length && !dictType.value && !props.selectData) initialization(val);
	},
	{ deep: true, immediate: true }
);

watch(
	() => dictType.value,
	(val) => {
		if (val) initFn();
	},
	{ immediate: true }
);

watch(
	() => store?.dict[unref(dictType)?.replace('GET', '')] || store?.com[unref(dictType)?.replace('GET', '')],
	(val) => {
		if (unref(dictType)) initialization(val);
	},
	{ deep: true, immediate: true }
);

watch(
	() => props.api,
	(val) => {
		if (val) {
			if (typeof val === 'string') {
				axios({
					method: 'get',
					url: API_HOST + val
				}).then((res) => {
					initialization(res.data || []);
				});
			}
			if (typeof val === 'function') {
				val().then((res) => {
					initialization(res.data || []);
				});
			}
		}
	},
	{ immediate: true }
);

/**
 * 获取选中的label
 * 获取选中的对象值
 * @param {*} val
 */
function selectChange(val) {
	emits('getLabel', unref(options).find((item) => item.value === val)?.label);
	emits(
		'getRow',
		unref(options).find((item) => item.value === val)
	);
}
/**
 * 数据处理
 * @param {[]} data 原始数据
 * @param {} fileType 处理{ label: 'dictLabel', value: 'dictValue' }对象
 */
function fileTypeFn(data, fileType = isString(props.fileType) ? JSON.parse(props.fileType) : props.fileType) {
	try {
		return data?.map((val) => {
			const obj = {
				label: val[fileType.label],
				value: val[fileType.value],
				disabled: val[fileType.disabled] || false
			};
			if (props.original) {
				return {
					...obj,
					...val
				};
			} else {
				return obj;
			}
		});
	} catch (error) {
		console.log(error);
	}
}
/**
 * 添加全部选项
 * @param {*} data 原始数据
 */
function needAllFn(data = []) {
	if (data) {
		const num = JSON.stringify(data).includes(JSON.stringify({ label: '全部', value: '' }));
		if (!num) data.unshift({ label: '全部', value: '' });
		return data;
	}
}

function initialization(list = props.list) {
	options.value = fileTypeFn(list);
	if (props.needAll) options.value = needAllFn(options.value);
}

// 初始化执行逻辑
function initFn() {
	if (unref(dictType)) {
		(store?.dict[unref(dictType)] || store?.com[unref(dictType)])?.();
	} else {
		initialization();
	}
}
</script>

<style lang="scss" scoped>
:deep(.el-select) {
	width: 100%;
}
</style>
